package avicit.bdp.dms.tdm.service;

import avicit.bdp.common.base.BaseService;
import avicit.bdp.common.dto.BdpPrmEngineResourceDTO;
import avicit.bdp.common.dto.StorageResourceConf;
import avicit.bdp.common.service.dto.DataSourceDTO;
import avicit.bdp.common.service.service.DataSourceService;
import avicit.bdp.common.utils.CheckParaUtils;
import avicit.bdp.common.utils.ConfigUtils;
import avicit.bdp.common.utils.database.DBUtils;
import avicit.bdp.common.utils.uploads.FileAdapterUtils;
import avicit.bdp.common.utils.uploads.IFileAdapter;
import avicit.bdp.core.poi.util.csv.ExportCSVUtil;
import avicit.bdp.dms.dss.dto.ColumnInfoDto;
import avicit.bdp.dms.prm.service.BdpPrmEngineResourceService;
import avicit.bdp.dms.tdm.dao.AssetDownloadDao;
import avicit.bdp.dms.tdm.dto.*;
import avicit.bdp.dms.tdm.service.adapter.DataServiceAdapter;
import avicit.bdp.dms.tdm.utils.ApplyServiceType;
import avicit.platform6.commons.utils.ComUtil;
import avicit.platform6.core.context.ThreadContextHelper;
import avicit.platform6.core.exception.BusinessException;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.*;

@Service
public class BdpAssetDownloadService extends BaseService<AssetDownloadDao, BdpAssetDownloadDTO> {

    /**
     * 临时文件保存路径
     */
    private final String csvPath = "/tmp/asset";

    @Autowired
    private DataSourceService dataSourceService;
    @Autowired
    private BdpAssetMountDataServiceService bdpAssetMountDataServiceService;
    @Autowired
    private BdpAssetService assetService;
    @Autowired
    private AssetPortalService assetPortalService;
    @Autowired
    private DataServiceAdapter dataServiceAdapter;
    @Autowired
    private BdpPrmEngineResourceService engineResourceService;

    public BdpAssetDownloadDTO getDownloadInfoByAssetId(String assetId, String userId) {
        BdpAssetDownloadDTO query = new BdpAssetDownloadDTO();
        query.setAssetId(assetId);
        query.setCreatedBy(userId);
        return this.selectOne(query);
    }

    public Map<String,Object> checkDataDownloadById(String assetId) {
        Map<String,Object> map = new HashMap<>();
        BdpAssetMountDataServiceDTO assetMountData = bdpAssetMountDataServiceService.queryByAssetId(assetId);
        CheckParaUtils.checkDbObjectValidity(assetMountData, logger, String.format("没有查到数据，请确保id:%s的资产是否存在", assetId));
        String userId = ThreadContextHelper.getUserId();
        if (StringUtils.isBlank(userId)) {
            userId = "1";
        }
        BdpAssetDownloadDTO assetDownLoadDTO = this.getDownloadInfoByAssetId(assetId, userId);
        if (assetDownLoadDTO != null) {
            map.put("status",assetDownLoadDTO.getStatus());
            if(assetDownLoadDTO.getStatus() == 3){
                map.put("fileId",assetDownLoadDTO.getId());
                map.put("fileName",assetDownLoadDTO.getFileName());
                map.put("fileDate",assetDownLoadDTO.getBeginTime());
            }
            return map;
        }
        String tableName = assetMountData.getTableName();
        DataSourceDTO dataSourceDTO = dataSourceService.selectByPrimaryKey(assetMountData.getDatasourceId());
        try {
            long size = DBUtils.countTableSize(dataSourceDTO, tableName, "");
            //直接下载的数据量   大于1万条数据，不能直接下载
            int downloadSize = ConfigUtils.getInstance().getInteger("system.downloadDataSize", 10000);
            if (size > downloadSize) {
                map.put("status",1);
                return map;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

        map.put("status",0);
        return map;
    }


    public String generateTempFile(String assetId) {
        BdpAssetDTO assetDTO = assetService.selectByPrimaryKey(assetId);
        CheckParaUtils.checkDbObjectValidity(assetDTO, logger, String.format("没有查到数据，请确保id:%s的资产是否存在", assetId));
        String fileName = assetDTO.getName();
        String userId = ThreadContextHelper.getUserId();
        if (StringUtils.isBlank(userId)) {
            userId = "1";
        }
        String filePath = csvPath + "/" + userId + "/" + fileName + ".csv";
        try {
            BdpAssetDownloadDTO assetDownLoadDTO = this.getDownloadInfoByAssetId(assetId, userId);
            //存在了 先删除
            if (assetDownLoadDTO != null) {
                assetDownLoadDTO.setStatus(2);
                assetDownLoadDTO.setBeginTime(new Date());
                assetDownLoadDTO.setFilePath(null);
                assetDownLoadDTO.setFileName(null);
                updateByPrimaryKey(assetDownLoadDTO);
                //fileAdapter.delete(filePath, true);
                //deleteByPrimaryKey(assetDownLoadDTO.getId());
            }else {

                BdpAssetDownloadDTO assetDownloadDTO = new BdpAssetDownloadDTO();
                assetDownloadDTO.setId(ComUtil.getId());
                assetDownloadDTO.setAssetId(assetId);
                assetDownloadDTO.setStatus(2);
                assetDownloadDTO.setBeginTime(new Date());
                assetDownloadDTO.setCreatedBy(userId);
                insert(assetDownloadDTO);
            }
            uploadMinio(userId,assetId,filePath,fileName);

        } catch (Exception e) {
            throw new BusinessException("上传失败:" + e.getMessage());
        }
        return filePath;
    }

    @Async
    public void uploadMinio(String userId, String assetId, String filePath, String fileName) throws IOException {


        IFileAdapter fileAdapter = FileAdapterUtils.getFileAdapterByProject(null);

        int pageSize = Integer.MAX_VALUE;

        Map<String, Object> map = dataServiceAdapter.getDataListFromDB(assetId, 1, pageSize, null);
        List<ColumnInfoDto> columnInfoDtoList = (List<ColumnInfoDto>) map.get("columnList");
        if (CollectionUtils.isEmpty(columnInfoDtoList)) {
            throw new BusinessException("无数据");
        }
        List<Object> tableHeader = new ArrayList<>();
        for (ColumnInfoDto columnInfo : columnInfoDtoList) {
            tableHeader.add(columnInfo.getName());
        }

        List<List<Object>> cellList = new ArrayList<>();
        List<Map<String, Object>> resultList = (List<Map<String, Object>>) map.get("resultList");
        if (CollectionUtils.isNotEmpty(resultList)) {
            List<Object> mapValuesList;

            for (Map<String, Object> dataMap : resultList) {
                mapValuesList = new ArrayList<>(dataMap.size());
                for (ColumnInfoDto columnInfo : columnInfoDtoList) {
                    mapValuesList.add(dataMap.get(columnInfo.getName()));
                }
                cellList.add(mapValuesList);
            }
        }
        String dirFile = csvPath + "/" + userId + "/";
        ExportCSVUtil.createCSVFile(tableHeader, cellList, dirFile, fileName);
        //上传oss
        fileAdapter.copyLocalToServer(filePath, filePath, true, true);

        BdpAssetDownloadDTO assetDownLoad = this.getDownloadInfoByAssetId(assetId, userId);
        assetDownLoad.setEndTime(new Date());
        assetDownLoad.setStatus(3);
        assetDownLoad.setFilePath(filePath);
        assetDownLoad.setFileName(fileName);
        updateByPrimaryKey(assetDownLoad);
    }


    public void downloadTempFile(String fileId, HttpServletResponse response) throws Exception {
        BdpAssetDownloadDTO assetDownLoad = this.selectByPrimaryKey(fileId);
        AssetLogDTO logDTO = assetPortalService.createAssetLog(fileId, ApplyServiceType.DOWNLOAD.getCode());

        try {
            String filePath = assetDownLoad.getFilePath();
            BdpPrmEngineResourceDTO engineResourceDTO =
                    engineResourceService.findDefaultEngineResource(1);
            CheckParaUtils.checkDbObjectValidity(engineResourceDTO, logger, String.format("请确保存在存储引擎"));
            StorageResourceConf conf = engineResourceDTO.getStorageResourceConf();
            IFileAdapter fileAdapter = FileAdapterUtils.getFileService(conf);
            fileAdapter.copyServerToLocal(filePath, filePath, false, true);
            fileAdapter.downloadFile(filePath, response);
            logDTO.setCallResult("下载数据成功");
            logDTO.setCallStatus(1);
        } catch (Exception e) {
            logDTO.setCallStatus(0);
            logDTO.setCallResult(e.getMessage());
            logger.error("下载数据异常", e);
        }
    }
}
